<?php


namespace Xin\Hint;

use Closure;
use Xin\Capsule\Manager;
use Xin\Hint\Contracts\Factory as HintFactory;
use Xin\Support\Arr;

/**
 * @mixin HintHandler
 */
class HintManager extends Manager implements HintFactory
{
	/**
	 * @var bool
	 */
	protected $lock = false;

	/**
	 * @var Closure
	 */
	protected $autoResolverCallback;

	/**
	 * @var array
	 */
	protected $config = [
		'defaults' => [
			'hint' => 'api',
		],
		'hints' => [
			'api' => [],
			'web' => [],
		],
	];

	/**
	 * 获取提示器
	 *
	 * @param string $name
	 * @return \Xin\Hint\Contracts\HintHandler
	 */
	public function hint($name = null)
	{
		return $this->driver($name);
	}

	/**
	 * 强制使用Api模式
	 *
	 * @return $this
	 */
	public function shouldUseApi()
	{
		return $this->shouldUse('api');
	}

	/**
	 * 强制使用Web模式
	 *
	 * @return $this
	 */
	public function shouldUseWeb()
	{

		return $this->shouldUse('web');
	}

	/**
	 * 使用指定的提示器
	 *
	 * @return $this
	 */
	public function shouldUse($name)
	{
		$this->lock = true;

		$this->setDefaultDriver($name);

		return $this;
	}

	/**
	 * 创建API响应器
	 * @param string $name
	 * @param array $config
	 * @return HintHandler
	 */
	protected function createApiDriver($name, $config)
	{
		return new HintHandler($config, new ApiRender());
	}

	/**
	 * 获取提示器配置
	 * @param array $config
	 * @return array
	 */
	public function newHintHandlerConfig($config)
	{
		return array_replace_recursive(Arr::only($this->getConfig('defaults'), [
			'error_code', 'success_code', 'success_msg',
		]), $config);
	}

	/**
	 * 设置自动完成提示器
	 *
	 * @param Closure $resolverCallback
	 */
	public function setAutoResolver(Closure $resolverCallback)
	{
		$this->autoResolverCallback = $resolverCallback;
	}

	/**
	 * @inerhitDoc
	 */
	public function getDefaultDriver()
	{
		if (!$this->lock && is_callable($this->autoResolverCallback)) {
			return call_user_func($this->autoResolverCallback);
		}

		return $this->getConfig('defaults.hint', 'api');
	}

	/**
	 * @inerhitDoc
	 */
	public function setDefaultDriver($name)
	{
		$this->setConfig('defaults.hint', $name);
	}

	/**
	 * @inerhitDoc
	 */
	public function getDriverConfig($name)
	{
		return $this->getConfig($name ? "hints.{$name}" : 'hints');
	}

	/**
	 * @return string
	 */
	protected function getDefault($type)
	{
		return Arr::get($this->config, "defaults.{$type}", 'default');
	}

}
